/*
    Heart of Gold engine management system
    Copyright (C) 2004 Heart of Gold development team

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package com.heartOfGold.model.megasquirtECU;

/*
 * A simple utility class to provide a workaround for the fact that
 * java does not support unsigned bytes, this is intended for use
 * with the megasquirt HOG_Component.
 * @author Ryan Higgins
 * @date 19 May 04
 * @version %I%, %G%
 */
public class UnsignedByte {
    //TODO add exception for out of range values
    private int[] bits;
    private static final int BYTE_NUM_BITS = 8;
    private static final int BYTE_MAX_VALUE = 255;
    private static final int NIBBLE_NUM_BITS = 4;

    public UnsignedByte() {
        bits = new int[BYTE_NUM_BITS];
    }

    public UnsignedByte(final int num) {
        bits = new int[BYTE_NUM_BITS];
        setValue(num);
        return;
    }

    public final void setValue(final int num) {
        if (num > BYTE_MAX_VALUE) {
            return;
        }
        int operand = num;
        for (int i = 0; i < BYTE_NUM_BITS; i++) {
            bits[i] = operand % 2;
            operand /= 2;
        }
        return;
    }

    public final int getValue() {
        int res = 0;
        for (int i = 0; i < BYTE_NUM_BITS; i++) {
            res += bits[i] * Math.pow(2, i);
        }
        return res;
    }

    public final int getUpperNibble() {
        int res = 0;
        for (int i = 0; i < NIBBLE_NUM_BITS; i++) {
            res += bits[i + NIBBLE_NUM_BITS] * Math.pow(2, i);
        }
        return res;
    }

    public final void setUpperNibble(final int num) {
        int operand = num;
        for (int i = NIBBLE_NUM_BITS; i < BYTE_NUM_BITS; i++) {
            bits[i] = operand % 2;
            operand /= 2;
        }
        return;
    }

    public final void setBit(final int bit, final int value) {
        if (bit >= BYTE_NUM_BITS) {
            return;
        }
        if (value >= 2) {
            return;
        }
        bits[bit] = value;
    }

    public final int getBit(final int bit) {
        if (bit >= BYTE_NUM_BITS) {
            return -1;
        }
        return bits[bit];
    }

    public final int getBits(final int offset, final int numBits) {
        int res = 0;
        for (int i = offset; i < numBits; i++) {
            res += bits[i + offset] * Math.pow(2, (i - offset));
        }
        return res;
    }

    // TODO check
    public final void setBits(final int offset, final int numBits,
            final int value) {
        int operand = value;
        for (int i = offset; i < numBits; i++) {
            bits[i] = operand % 2;
            operand /= 2;
        }
        return;
    }
    /*
     * public static void main(String[] args){ UnsignedByte test = new
     * UnsignedByte(15); int upper = test.getUpperNibble(); int value =
     * test.getValue(); int bits = test.getBits(0,2);
     * System.out.println("first two bits = " + bits); test.setBits(0,2, 2);
     * bits = test.getBits(0,2);
     * System.out.println("After setting to 2 first two bits = " + bits);
     * System.out.println("the third bit = " + test.getBit(2));
     *
     * System.out.println("Upper nibble is " + upper); test.setUpperNibble(12);
     * System.out.println("After setting to 12 upper nibble = " +
     * test.getUpperNibble()); System.out.println("Return value is " + value);
     * int some = test.getBits(0, 2); System.out.println("getBits(0, 2) gives "
     * + some); }
     */
}
